package com.example.sdcardoptdemo;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.documentfile.provider.DocumentFile;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.util.Log;
import android.view.View;
import android.widget.TextView;


import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final int REQ_RW_SD = 0x88;
    private TextView tv_text;
    private String rootPath = "";

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_text = findViewById(R.id.tv_text);

        test();
    }

    private void test() {
        String sdpath = "";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            sdpath = externalSDCardPath();
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                sdpath = getPhysicalExternalFilePathAboveM();
            }
        }
        rootPath = sdpath;

        if (DocumentsUtils.checkWritableRootPath(this, rootPath)) {
            showOpenDocumentTree();
            return;
        }
        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < 10; i++) {
            File fff = new File(rootPath, "djsdhkjdhkj" + i);
            boolean b = DocumentsUtils.mkdirs(this, fff);
            sb.insert(0, fff.getAbsolutePath() + ":" + b + "\n");
        }

        DocumentFile f = DocumentsUtils.getDocumentFile(new File(sdpath), true, this);
        if (f.exists()) {
            DocumentFile[] files = f.listFiles();
            for (int i = 0; i < files.length; i++) {
                sb.append(files[i].getName() + "\n");
            }
        }
        File testFile = new File(rootPath, "djsdhkjdhkj0/");
        DocumentFile t = DocumentsUtils.getDocumentFile(testFile, false, this);
        t.createFile("txt", "testtext.txt");
        OutputStream testfileOut = DocumentsUtils.getOutputStream(this, testFile);
        try {
            testfileOut.write("shdhksjhghjghjsaghjs".getBytes(), 0, "shdhksjhghjghjsaghjs".getBytes().length);
            testfileOut.flush();
            testfileOut.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        tv_text.setText(sdpath + "\nresult:" + sb.toString());
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public String externalSDCardPath() {
        String externalSDCardPath = "";
        try {
            StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
            // 7.0才有的方法
            List<StorageVolume> storageVolumes = storageManager.getStorageVolumes();
            Class<?> volumeClass = Class.forName("android.os.storage.StorageVolume");
            Method getPath = volumeClass.getDeclaredMethod("getPath");
            Method isRemovable = volumeClass.getDeclaredMethod("isRemovable");
            getPath.setAccessible(true);
            isRemovable.setAccessible(true);
            for (int i = 0; i < storageVolumes.size(); i++) {
                StorageVolume storageVolume = storageVolumes.get(i);
                String mPath = (String) getPath.invoke(storageVolume);
                Boolean isRemove = (Boolean) isRemovable.invoke(storageVolume);
                if (isRemove) {
                    externalSDCardPath = mPath;
                }
                Log.i("tag2", "mPath is === " + mPath + "isRemoveble == " + isRemove);
            }
        } catch (Exception e) {
            Log.i("tag2", "e == " + e.getMessage());
        }
        return externalSDCardPath;
    }

    private void showOpenDocumentTree() {
        Intent intent = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            StorageManager sm = this.getSystemService(StorageManager.class);

            StorageVolume volume = sm.getStorageVolume(new File(rootPath));

            if (volume != null) {
                intent = volume.createAccessIntent(null);
            }
        }

        if (intent == null) {
            intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
        }
        startActivityForResult(intent, DocumentsUtils.OPEN_DOCUMENT_TREE_CODE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case DocumentsUtils.OPEN_DOCUMENT_TREE_CODE:
                if (data != null && data.getData() != null) {
                    Uri uri = data.getData();
                    DocumentsUtils.saveTreeUri(this, rootPath, uri);
                    test();
                }
                break;
            default:
                break;
        }
    }

    /**
     * 6.0使用此方法获取外置SD卡路径，尝试过反射{@link StorageManager# getVolumeList}
     * 但StorageVolume非Public API 编译不通过（7.0改为公开API）,故使用UserEnvironment
     * 的内部方法getExternalDirs获取所有的路径，通过{@link Environment#isExternalStorageRemovable(File)}
     * 判断若removable则为外部存储
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private static String getPhysicalExternalFilePathAboveM() {
        try {
            //===========================获取UserEnvironment================
            Class<?> userEnvironment = Class.forName("android.os.Environment$UserEnvironment");
            Method getExternalDirs = userEnvironment.getDeclaredMethod("getExternalDirs");
            getExternalDirs.setAccessible(true);
            //========获取构造UserEnvironment的必要参数UserId================
            Class<?> userHandle = Class.forName("android.os.UserHandle");
            Method myUserId = userHandle.getDeclaredMethod("myUserId");
            myUserId.setAccessible(true);
            int mUserId = (int) myUserId.invoke(UserHandle.class);
            Constructor<?> declaredConstructor = userEnvironment.getDeclaredConstructor(Integer.TYPE);
            // 得到UserEnvironment instance
            Object instance = declaredConstructor.newInstance(mUserId);
            File[] files = (File[]) getExternalDirs.invoke(instance);
            for (int i = 0; i < files.length; i++) {
                if (Environment.isExternalStorageRemovable(files[i])) {
                    return files[i].getPath();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
//————————————————
//    版权声明：本文为CSDN博主「xingnan4414」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。
//    原文链接：https://blog.csdn.net/xingnan4414/article/details/79388972
//

}